using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Aces4All.Logger
{
    /// <summary>
    /// Clased used for writing log entries to text-based log files
    /// </summary>
    public class TextLog : ILog
    {
        #region public constructors

        /// <summary>
        /// Creates new TextLog instance
        /// </summary>
        /// <param name="fullPath">
        /// Full path of log file
        /// </param>
        /// <param name="source">
        /// Source application making lof entries
        /// </param>
        /// <param name="delimitted">
        /// Indicates if log file is delimitted
        /// </param>
        /// <param name="separator">
        /// Character(s) used to separate fields of log file
        /// </param>
        public TextLog(string fullPath, string source, 
            bool delimitted, string separator)
        {
            FileInfo logFile = new FileInfo(fullPath);
            this.m_Log = fullPath;
            this.m_FileExtension = logFile.Extension;
            this.m_FileName = logFile.Name;
            this.m_FolderPath = logFile.DirectoryName;
            this.m_Source = source;
            this.m_Delimitted = delimitted;
            this.m_Separator = separator;
        }

        /// <summary>
        /// Creates new instance of TextLog
        /// </summary>
        /// <param name="logFolderPath">
        /// Full path of folder containing log file
        /// </param>
        /// <param name="sourceApplication">
        /// Source application making log entries
        /// </param>
        /// <param name="timeStamp">
        /// Indicates if a time stamp should me made part 
        /// if log file's name (used to generate unique name)
        /// </param>
        /// <param name="fileExtension">
        /// The file extension of the log file
        /// </param>
        /// <param name="create">
        /// Indicates if a new log file should be created
        /// if it does not already exists
        /// </param>
        /// <param name="delimitted">
        /// Indicates if logfile fields are delinitted
        /// </param>
        /// <param name="separator">
        /// Character(s) used to separate log file fields
        /// </param>
        public TextLog(string logFolderPath, string sourceApplication, 
            bool timeStamp, string fileExtension, bool create, 
            bool delimitted, string separator)
        {
            this.m_FolderPath = logFolderPath;
            this.m_Source = sourceApplication;
            this.m_FileExtension = fileExtension;
            this.m_FileName = this.m_Source;
            this.m_Delimitted = delimitted;
            this.m_Separator = separator;

            if (timeStamp)
            {
                string stamp = Aces4All.Date.TimeStamp.GetTimestamp();
                this.m_FileName = this.m_FileName + "_" + stamp;
            }

            this.m_Log = this.m_FolderPath + "\\" + this.m_FileName
                    + "." + this.m_FileExtension;
        }

        #endregion

        #region public properties

        private string m_Log;
        /// <summary>
        /// Gets full path of log file.
        /// </summary>
        public string Log
        {
            get
            {
                return this.m_Log;
            }
        }

        private string m_Source;
        /// <summary>
        /// Gets name of source application for log entries.
        /// </summary>
        public string Source
        {
            get
            {
                return this.m_Source;
            }
        }

        private string m_FileName;
        /// <summary>
        /// Gets name of log file.
        /// </summary>
        public string FileName
        {
            get
            {
                return this.m_FileName;
            }
        }

        private string m_FolderPath;
        /// <summary>
        /// Gets path of folder containing log file
        /// </summary>
        public string FolderPath
        {
            get
            {
                return this.m_FolderPath;
            }
        }

        private string m_FileExtension;
        /// <summary>
        /// Gets file extension of log file
        /// </summary>
        public string FileExtension
        {
            get
            {
                return this.m_FileExtension;
            }
        }

        private bool m_Delimitted;
        /// <summary>
        /// Indicates if log file is a delimitted text file
        /// </summary>
        public bool Delimitted
        {
            get
            {
                return this.m_Delimitted;
            }
        }

        private string m_Separator;
        /// <summary>
        /// Character(s) used to separate fields in log file
        /// </summary>
        public string Separator
        {
            get
            {
                return this.m_Separator;
            }
        }

        #endregion

        #region public methods

        /// <summary>
        /// Writes entry to log file
        /// </summary>
        /// <param name="entry">Text entry to write to log file</param>
        public void WriteEntry(LogEntry entry)
        {
            FileInfo logFile = new FileInfo(this.m_Log);
            string textEntry = this.FormatEntry(entry.GetValues());

            using (StreamWriter logWriter = logFile.AppendText())
            {
                logWriter.WriteLine(textEntry);
                logWriter.Flush();
                logWriter.Close();
            }
        }

        #endregion

        #region private methods

        //public void WriteEntry(string[] entries)
        //{
        //    string entry = this.FormatEntry(entries);
        //    this.WriteEntry(entry);
        //}

        /// <summary>
        /// Formats string array <paramref name="values"/> 
        /// as text that can be written to log file.
        /// </summary>
        /// <param name="values">
        /// String array to be written to log file
        /// </param>
        /// <returns>String of text that can be written to log file</returns>
        private string FormatEntry(string[] values)
        {
            string entry = String.Join(this.m_Separator, values);
            return entry;
        }

        /// <summary>
        /// Creates new log file and writes header.
        /// </summary>
        private void CreateLogFile()
        {
            string[] fields = Enum.GetNames(typeof(LogFields));
            string header = this.FormatEntry(fields);
            FileInfo logFile = new FileInfo(this.m_Log);

            if (!logFile.Exists)
            {
                using (StreamWriter logWriter = logFile.CreateText())
                {
                    logWriter.WriteLine(header);
                    logWriter.Flush();
                }
            }
        }

        #endregion
    }
}
